#include "bit_reversed_counter.h"

/**
 * Reverse the bits of v, assuming we have n bits
 * @param v integer to reverse
 * @param n number of bits of v
 * @return the reversed number
 */
int reverseBits(int v, int n)
{
	int r = 0, i;
	for(i = n; i > 0; i--)
	{
		// set the bit i of the result
		r += v%2 << (i-1);
		// remove the LSB of v
		v /= 2;
	}
	return r;
}

/**
 * Create and initialize a bit reversal counter
 * @return a new bit reversed counter initialized
 */ 
brc bit_reversed_counter_Init()
{
	brc b;	
	b.counter = 0;
	b.depth = 0;
	return b;
}

/**
 * swap the bits of counter which are less than depth
 * @param counter 
 * @param depth
 * @return 
 */ 
static int swapBits(int counter, int depth)
{
	int header = 1 << (depth-1); //2^depth
	int x = counter - header;
	return header + reverseBits(x, depth-1);
}

/**
 * increment the counter and return the new value in reversed bits
 * @param b a pointer to the bit reversed counter to increment
 * @return the new value in reversed bits
 */
int brc_Increment(brc *b)
{
	b->counter ++;
	//return b->counter;
	if(b->counter >= (1 << b->depth))
		b->depth ++;
	
	return swapBits(b->counter, b->depth);
}

/**
 * return the current value of the counter in reversed bits, and decrement the counter
 * if the counter is at 0, return 0 and doesn't decrement it
 * @param b a pointer to the bit reversed counter
 * @return the current value of the counter in reversed bits
 */
int brc_Decrement(brc *b)
{
	if(b->counter == 0) // do not decrement less than 0
		return 0;
	
	//int t = b->counter;
	//b->counter --;
	//return t;
	
	int result = swapBits(b->counter, b->depth);
	
	b->counter --;
	if(b->counter < (1 << (b->depth-1)))
		b->depth --;
	
	return result;
}

/**
 * return the current value of the counter NOT in reversed bits
 * @param b a pointer to the bit reversed counter
 * @return the current value of the counter NOT in reversed bits
 */
int brc_getRealValue(brc *b)
{
	return b->counter;
}


